package ven.spots;

import java.io.IOException;
import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

/**
 * 
 * @author mattz
 * @ref (GUI Threading)- http://blog.ocszone.com/blog/android-sdk-timers-and-gui-update/ 
 */
public class SpotManagerActivity extends Activity {
	//Threading stuff.
	private static final int UPDATE_STUFF_ON_DIALOG = 999;
	private Handler handlerTimer =  new Handler();
	
	//Database connections and adapters
	private DatabaseConnector2   dbc = new DatabaseConnector2();
    private ArrayList<SpotData> data = null;
    private SpotDataListAdapter adapter;
	
    //Objects for the dynamic views on the screen
	private static Button setStateBtn;
	private ListView spotDataList;
	private static TextView macTV;
	private static TextView rgbTV;
	private static TextView stateTV;
	
	//Hold info about the node we are managing
	private static SpotNode node;
	
	/**
	 * Do stuff to update the backend.  No gui interactions.  Update
	 * the "node" field var.  Update the "data" field var.  
	 */
	private Runnable taskUpdateStuffOnDialog = new Runnable() {
	       public void run() {     
	    	   //Attempt to update the "node" field var.
	    	   try {
	    		   SpotNode newNode = dbc.getNode(node.getIeee());
	    		   if (newNode != null) {
	    			   node = newNode;
	    		   }
	    		   Log.d("test", "Thread updated node info.");
	    	   } catch (IOException e) {
	    		   Log.d("test", e.getMessage());
	    	   }
	    	   
	    	   //Update the "data" field var
	    	   try {
	    		   data = dbc.getData(node.getIeee());
	    		   Log.d("test", "Thread updated node data.");
	    	   } catch (IOException e) {
	    		   Log.d("test", e.getMessage());
	    	   }
	   
	            Message msg = new Message();
	            msg.what = UPDATE_STUFF_ON_DIALOG;
	            handlerEvent.sendMessage(msg); 
	            //Do this again in 15 seconds          
	            handlerTimer.postDelayed(this, 15000);
	    }
	};
	
	/**
	 * Update the gui based on the changes made by the thread
	 * running in the background.  Update the spot's status,
	 * the listview of data, and the state of the button to
	 * flash the spot's lights.
	 */
	private Handler handlerEvent =  new Handler() {
	    @Override
	    public void handleMessage(Message msg) {
	        switch (msg.what) {
	        	case UPDATE_STUFF_ON_DIALOG: {
	        		SpotManagerActivity.setButtonState();
	        		SpotManagerActivity.setSpotDetails();
	        		if (data != null && spotDataList != null) {
	                	adapter = new SpotDataListAdapter(SpotManagerActivity.this,
	                									  R.layout.spot_data_row, data);
	                	spotDataList.setAdapter(adapter);
	                }
	        	}
	            break;         
	        	default: {
	        		super.handleMessage(msg);
	        	}
	            break;         
	        }
	    }
	};
	
	/**
	 * Run when activity is created...
	 */
	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.spot_manager_layout);
         
        handlerTimer.removeCallbacks(taskUpdateStuffOnDialog);
        handlerTimer.postDelayed(taskUpdateStuffOnDialog, 100);
        
        node = this.getNodeFromIntent();
        this.getGuiObjects();
        SpotManagerActivity.setSpotDetails();
        SpotManagerActivity.setButtonState();
        
        setStateBtn.setOnClickListener( new OnClickListener() {
			@Override
			public void onClick(View v) {
				DatabaseConnector2 dbc = new DatabaseConnector2();
				try {
					dbc.setState(node.getIeee(), 255, 255, 255);
				} catch (IOException e) {
					Log.d("test", e.getMessage());
				}
				SpotManagerActivity.setStateBtn.setEnabled(false);
			}
		});
        
        //Fill listview with data
        try {
			data = dbc.getData(node.getIeee());
			adapter = new SpotDataListAdapter(this, R.layout.spot_data_row, data);
			spotDataList.setAdapter(adapter);
		} catch (IOException e) {
			Log.d("test", e.getMessage());
		}
	}
	
	/**
	 * Make a SpotNode object from data based to this activity in an intent.
	 * @return SpotNode
	 */
	private SpotNode getNodeFromIntent() {
		//Get extra values from the intent to later be thrown into appropriate textviews
        Intent intent = this.getIntent();
        int state  = intent.getIntExtra("state", -1);
        int red    = intent.getIntExtra("red", 0);
        int green  = intent.getIntExtra("green", 0);
        int blue   = intent.getIntExtra("blue", 0);
        String mac = intent.getStringExtra("ieee");
        SpotNode newNode = new SpotNode(mac, state);
        newNode.setRed(red);
        newNode.setGreen(green);
        newNode.setBlue(blue);
        return newNode;
	}
	
	/**
	 * Get gui objects generated by xml
	 */
	private void getGuiObjects() {
		spotDataList = (ListView)this.findViewById(R.id.spotDataList);
        setStateBtn = (Button)this.findViewById(R.id.setStateBtn);
        macTV = (TextView)this.findViewById(R.id.smMACTV);
        rgbTV = (TextView)this.findViewById(R.id.smRGBTV);
        stateTV = (TextView)this.findViewById(R.id.smStateTV);
	}
	
	/**
	 * Set the details of the current sunspot on the gui
	 */
	private static void setSpotDetails() {
        if (macTV != null) {
        	macTV.setText("MAC  :  " + node.getIeee());
        }
        if (rgbTV != null) {
        	rgbTV.setText("RGB  :  (" + node.getRed() + 
        			      ", " + node.getGreen() + ", "
        			      + node.getBlue() + ")");
        }
        if (stateTV != null) {
        	stateTV.setText("State:  " + node.getState());
        }
	}
	
	/**
	 * Determine whether or not the set spot flashing button should
	 * be enabled.
	 */
	private static void setButtonState() {
		if (setStateBtn != null) {
        	if (node.getState() == 1) {
        		//Spot is either offline or online(idle)
        		setStateBtn.setEnabled(true);
        		setStateBtn.setText(R.string.stateBtnEnabled);
        	} else {
        		//Spot is already flashing or error'd
        		setStateBtn.setEnabled(false);
        		setStateBtn.setText(R.string.stateBtnDisabled);
        	}
        }
	}
	
    /**
     * Fills a ListView with TextViews representing SpotData object
     * @author Matthew Zizzi
     * Referenced: http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/
     */
	private class SpotDataListAdapter extends ArrayAdapter {
    	private ArrayList<SpotData> data;
    	
    	/**
    	 * Overridden constructor.  Sets arraylist of data to be used as a field var.
    	 * @param context
    	 * @param textViewResourceId
    	 * @param _data ArrayList<SpotData> of data to be used as a field var.
    	 */
		public SpotDataListAdapter(Context context,
								   int textViewResourceId,
								   ArrayList<SpotData> _data) {
			super(context, textViewResourceId, _data);
            this.data = _data;
		}
		
		public View getView(int position, View convertView, ViewGroup parent) {
			View v = convertView;
			if (v == null) {
				LayoutInflater vi;
				vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				v = vi.inflate(R.layout.spot_data_row, null);
			}
			
			SpotData sd = this.data.get(position);
			if (sd != null) {
				//Get instances of the needed textfields so we can add dynamic data
				TextView timeTV  = (TextView)v.findViewById(R.id.sdTimeTV);
				TextView stateTV = (TextView)v.findViewById(R.id.sdStateTV);
				TextView lightTV = (TextView)v.findViewById(R.id.sdLightTV);
				
				if (timeTV != null) {
					timeTV.setText("Time :  " + sd.getStrDate());
				}
				if (stateTV != null) {
					stateTV.setText("State:  " + sd.getState());
				}
				if (lightTV != null) {
					lightTV.setText("Light:  " + sd.getLight());
				}
			}//End null sd check
			return v;
		}//End getView
    }//End SpotDataListAdapter
}